home *** CD-ROM | disk | FTP | other *** search
/ SGI Developer Toolbox 6.1 / SGI Developer Toolbox 6.1 - Disc 1.iso / toolbox / src / exampleCode / opengl / GLUT / progs / demos / yacme / Editor.c next >
Encoding:
C/C++ Source or Header  |  1996-11-11  |  30.2 KB  |  1,375 lines

  1. /*===========================================================================*/
  2. /*
  3. /*                YACME
  4. /*            Yet Another ColorMap Editor
  5. /*
  6. /*            Patrick BOUCHAUD - 1993
  7. /*                          SGI Switzerland
  8. /*
  9. /*                    Converted to OpenGL using GLUT
  10. /*
  11. /*===========================================================================*/
  12.  
  13. #include <stdio.h>
  14. #include <string.h>
  15. #include <stdlib.h>
  16. #include <math.h>
  17. #include <GL/glut.h>
  18.  
  19. #include "mallocbis.h"
  20.  
  21. /* For portability... */
  22. #undef fsqrt
  23. #define fsqrt(_a)     sqrt(_a)
  24.  
  25. #define    SUP(a,b)    ( ((a)>(b)) ? (a) : (b) )
  26. #define    INF(a,b)    ( ((a)<(b)) ? (a) : (b) )
  27. #define    ABS(a)        ( ((a)<0) ? -(a) : (a) )
  28. #define    POINT        1
  29. #define    CURVE        2
  30. #define    LEFT_TAN    3
  31. #define    RIGHT_TAN    4
  32. #define    MANUAL        1
  33. #define    CONTINUOUS    2
  34.  
  35. #define    CONSTANT    1
  36. #define    LINEAR        2
  37. #define    POLYNOMIAL    3
  38.  
  39. #define    TabCmpnt(c,n)    TabCmpnt[(n)*4+(c)]
  40.  
  41. #define    MAXNDX    (dimlut-1)
  42.  
  43. #define    WINHEIGHT    381
  44. #define    WINWIDTH    318
  45.  
  46. #define LUTRATIO    ((float)MAXNDX/255.)
  47.  
  48. #define    LEFT        LUTRATIO*(-5.)
  49. #define    RIGHT        LUTRATIO*(260.)
  50. #define    BOTTOM        LUTRATIO*(-5.)
  51. #define    TOP            LUTRATIO*(315.)
  52. #define    TANLEN        LUTRATIO*(25.)
  53.  
  54. typedef float Matrix[4][4];
  55.  
  56. typedef struct    {
  57.     float    x0, y0,
  58.         x1, y1;
  59. } Tangente;
  60.  
  61. typedef struct UserPointStruct    {
  62.  
  63.     float        x, y;
  64.     Tangente    tg;
  65.     int            mode;
  66.     float        polynome[4];
  67.     struct        UserPointStruct *next, *last;
  68.  
  69. } UserPoint;
  70.  
  71. void ResetCMap(void);
  72. void ApplyCMap(void);
  73. void YACME_makeMenu(void);
  74. extern void invertmat(float from[4][4], float to[4][4]);
  75.  
  76. static UserPoint *FreePointList = NULL;
  77. #define    newPoint( point ) newItem( point, FreePointList, UserPoint )
  78. #define    freePoint( point ) freeItem( point, FreePointList )
  79.  
  80. typedef struct    {
  81.     int    type,
  82.         cmpnt,
  83.         ndx;
  84.  
  85.     UserPoint *upoint;
  86. } PickObject;
  87.  
  88. struct {
  89.     int leftdown, middledown, rightdown;
  90. } mouse;
  91.  
  92. void YACME_pick( int mx, int my, PickObject *obj );
  93. void YACME_update( int cmpnt, UserPoint *upoint );
  94. int    YACME_get( unsigned long *table );
  95.  
  96. void    DeletePoint( int cmpnt, UserPoint *upoint );
  97. int    MovePoint( int, int );
  98. int    MoveTangente( int, int, int );
  99. int    InsertPoint( PickObject *obj );
  100.  
  101. void    GetPolynome( int mode,
  102.         float a0, float b0, float t0,
  103.         float a1, float b1, float t1,
  104.         float coeff[4] );
  105. void    OrthoTransform( int mx, int my, float *x, float *y );
  106. float    Polynome4( float x, float *polynome );
  107.  
  108. static int    DrawCurve[4] = { 1, 1, 1, 1, },
  109.         modifiedCurve[4] = { 1, 1, 1, 1 },
  110.         YACME_refresh = MANUAL,
  111.         curCmpnt = 0, curType = 0,
  112.         Mousex, Mousey;
  113.  
  114. static float *TabCmpnt;
  115. static long    YACME_menu = 0, YACME_switch_menu = 0,
  116.     YACME_mode_menu, YACME_edit_menu;
  117. static int YACME_win = 0, W, H , update = 0;
  118. static UserPoint *userPoint[4], *userPointSvg[4], *curPoint = NULL;
  119.  
  120. static void Redraw( void );
  121. static void Reshape( int, int );
  122. static void Mouse( int, int, int, int );
  123. static void Motion( int, int );
  124. static void Key( unsigned char, int, int );
  125. static void Special( int, int, int );
  126. static void YACME_menuFunc( int );
  127.  
  128. typedef void (*CallBack)(void);
  129. static CallBack newmapCB, applyCB;
  130. static int dimlut;
  131.  
  132. /*---------------------------------------------------------------------------*/
  133. /*            YACME_init
  134. /*---------------------------------------------------------------------------*/
  135. void
  136. YACME_init(
  137.     int x, int y, int w, int h,
  138.     int dim, float **list,
  139.     CallBack newmapFunc, CallBack applyFunc)
  140. {
  141.     int    i, j;
  142.     UserPoint *userpoint;
  143.  
  144.     if (YACME_win) return;
  145.  
  146.     dimlut = dim;
  147.     newmapCB = newmapFunc;
  148.     applyCB = applyFunc;
  149.  
  150.     if (*list==NULL)
  151.     {
  152.         *list = TabCmpnt = (float *) malloc( 4*dimlut*sizeof(float) );
  153.         for (i=0; i<4; i++)
  154.         {
  155.             newPoint( userPoint[i] );
  156.             userpoint = userPoint[i];
  157.             userpoint->mode = POLYNOMIAL;
  158.             userpoint->x = 0.;
  159.             userpoint->y = 0.;
  160.             userpoint->last    = NULL;
  161.             userpoint->tg.x0 = 0.;
  162.             userpoint->tg.y0 = 0.;
  163.             userpoint->tg.x1 = TANLEN;
  164.             userpoint->tg.y1 = 0.;
  165.     
  166.             newPoint( userpoint->next );
  167.             userpoint = userpoint->next;
  168.             userpoint->mode = POLYNOMIAL;
  169.             userpoint->x = (float)MAXNDX;
  170.             userpoint->y = (float)MAXNDX;
  171.             userpoint->last    = userPoint[i];
  172.             userpoint->next    = NULL;
  173.             userpoint->tg.x0 = (float)(MAXNDX-TANLEN);
  174.             userpoint->tg.y0 = (float)MAXNDX;
  175.             userpoint->tg.x1 = (float)MAXNDX;
  176.             userpoint->tg.y1 = (float)MAXNDX;
  177.         }
  178.     }
  179.     else
  180.     {
  181.         UserPoint *upoint[4], *lastupoint[4]={0,0,0,0};
  182.  
  183.         TabCmpnt = *list;
  184.         for (i=0; i<dim; i++)
  185.         {
  186.             for (j=0; j<4; j++)
  187.             {
  188.                 if (i==0)
  189.                 {
  190.                     newPoint( userPoint[j] );
  191.                     upoint[j] = userPoint[j];
  192.                 }
  193.                 else
  194.                 {
  195.                     newPoint( upoint[j]->next );
  196.                     upoint[j] = upoint[j]->next;
  197.                 }
  198.                 upoint[j]->next = NULL;
  199.                 upoint[j]->last = lastupoint[j];
  200.                 upoint[j]->mode = LINEAR;
  201.                 upoint[j]->x = (float)i;
  202.                 upoint[j]->y = (float)MAXNDX*TabCmpnt(j,i);
  203.                 if (i==0)
  204.                 {
  205.                     upoint[j]->tg.x0 = 0.;
  206.                     upoint[j]->tg.y0 = 0.;
  207.                     upoint[j]->tg.x1 = TANLEN;
  208.                     upoint[j]->tg.y1 = 0.;
  209.                 }
  210.                 else
  211.                 {
  212.                     float    slope = upoint[j]->y - upoint[j]->last->y,
  213.                             dx = TANLEN/fsqrt(slope*slope + 1),
  214.                             dy = slope*dx;
  215.                     upoint[j]->tg.x0 = upoint[j]->x - dx;
  216.                     upoint[j]->tg.y0 = upoint[j]->y - dy;
  217.                     upoint[j]->tg.x1 = upoint[j]->x + dx;
  218.                     upoint[j]->tg.y1 = upoint[j]->y + dy;
  219.                 }
  220.  
  221.                 lastupoint[j] = upoint[j];
  222.             }
  223.         }
  224.     }
  225.  
  226. /*
  227.     TabComponents update
  228.     --------------------
  229. */
  230.     for (i=0; i<4; i++)
  231.     {
  232.         for (userpoint=userPoint[i]; userpoint!=NULL; userpoint=userpoint->next)
  233.             YACME_update( i, userpoint );
  234.     }
  235.     ApplyCMap();
  236.  
  237.     if (!YACME_win)
  238.     {
  239.         glutInitDisplayMode( GLUT_RGB | GLUT_DOUBLE );
  240.         glutInitWindowPosition( x, y );
  241.         glutInitWindowSize( w, h );
  242.         YACME_win = glutCreateWindow( "LUT editor" );
  243.         glutDisplayFunc( Redraw );
  244.         glutReshapeFunc( Reshape );
  245.         glutMouseFunc( Mouse );
  246.         glutMotionFunc( Motion );
  247.         glutPassiveMotionFunc( Motion );
  248.         glutSpecialFunc( Special );
  249.         glutKeyboardFunc( Key );
  250.         
  251.         glMatrixMode( GL_PROJECTION );
  252.         glLoadIdentity();
  253.         glOrtho( LEFT, RIGHT, BOTTOM, TOP, -1., 1. );
  254.  
  255.         glClearColor( 0.66, 0.66, 0.66, 1. );
  256.         glClear( GL_COLOR_BUFFER_BIT );
  257.         glShadeModel( GL_FLAT );
  258.         glutSwapBuffers();
  259.  
  260.         YACME_makeMenu();
  261.     }
  262. }
  263.  
  264. /*---------------------------------------------------------------------------*/
  265. /*    Key
  266. /*---------------------------------------------------------------------------*/
  267. static void
  268. Key( unsigned char key, int x, int y )
  269. {
  270.     UserPoint *previousPoint;
  271. #if 1
  272.     switch (key)
  273.     {
  274.         case 27:    /* Escape */
  275.             exit(0);
  276.             break;
  277.  
  278.         case 127:    /* BackSpace */
  279.         case 8:        /* Delete */
  280.             if (!curPoint) return;
  281.             previousPoint = (curPoint->last ? curPoint->last : userPoint[curCmpnt]);
  282.             DeletePoint( curCmpnt, curPoint );
  283.             modifiedCurve[curCmpnt] = 1;
  284.             update = 1;
  285.             curPoint = previousPoint;
  286.             break;
  287.     }
  288.     glutPostRedisplay();
  289. #else
  290.     fprintf(stderr, "Key pressed = %d\n", key );
  291. #endif
  292. }
  293.  
  294. /*---------------------------------------------------------------------------*/
  295. /*      Special
  296. /*---------------------------------------------------------------------------*/
  297. static void
  298. Special( int key, int xx, int yy )
  299. {
  300.     int x, y, minx, maxx;
  301.     float dx, dy;
  302.     if (curPoint == NULL ) return;
  303.     if (curPoint->next == NULL) return;
  304.     if (curPoint->last == NULL) return;
  305.  
  306.     x = (int)curPoint->x;
  307.     y = (int)curPoint->y;
  308.  
  309.     minx = (int)curPoint->last->x; minx++;
  310.     maxx = (int)curPoint->next->x; maxx--;
  311.  
  312.     switch (key)
  313.     {
  314.         case GLUT_KEY_LEFT:
  315.             if (x > minx) x--;
  316.             break;
  317.  
  318.         case GLUT_KEY_RIGHT:
  319.             if (x < maxx) x++;
  320.             break;
  321.  
  322.         case GLUT_KEY_UP:
  323.             if (y < MAXNDX) y++;
  324.             break;
  325.  
  326.         case GLUT_KEY_DOWN:
  327.             if (y > 0) y--;
  328.             break;
  329.     }
  330.  
  331.     dx = (float)x - curPoint->x;
  332.     curPoint->x += dx;
  333.     curPoint->tg.x0 += dx;
  334.     curPoint->tg.x1 += dx;
  335.  
  336.     dy = (float)y - curPoint->y;
  337.     curPoint->y = y;
  338.     curPoint->tg.y0 += dy;
  339.     curPoint->tg.y1 += dy;
  340.  
  341.     update = 1;
  342.     glutPostRedisplay();
  343. }
  344.  
  345. /*---------------------------------------------------------------------------*/
  346. /*    Reshape
  347. /*---------------------------------------------------------------------------*/
  348. static void
  349. Reshape( int w, int h )
  350. {
  351.     glViewport( 0, 0, w, h );
  352.     W = w;
  353.     H = h;
  354.     glutPostRedisplay();
  355. }
  356.  
  357. /*---------------------------------------------------------------------------*/
  358. /*    Mouse
  359. /*---------------------------------------------------------------------------*/
  360. static void
  361. Mouse( int button, int state, int x, int y )
  362. {
  363.     PickObject    object;
  364.  
  365.     y = H-y;
  366.     switch (button)
  367.     {
  368.         case GLUT_RIGHT_BUTTON:
  369.             mouse.rightdown = (state==GLUT_DOWN);
  370.             break;
  371.  
  372.         case GLUT_MIDDLE_BUTTON:
  373.             mouse.middledown = (state==GLUT_DOWN);
  374.             break;
  375.  
  376.         case GLUT_LEFT_BUTTON:
  377.             mouse.leftdown = (state==GLUT_DOWN);
  378.             if (mouse.leftdown)
  379.             {
  380.                 YACME_pick( x, y, &object );
  381.                 curType = object.type;
  382.                 switch ( object.type )
  383.                 {
  384.                     case CURVE:
  385.                         if (curType=InsertPoint( &object ) != 0)
  386.                         {
  387.                             curPoint = object.upoint;
  388.                             curCmpnt = object.cmpnt;
  389.                         }
  390.                         else curPoint = NULL;
  391.                         break;
  392.  
  393.                     case POINT:
  394.                     case LEFT_TAN:
  395.                     case RIGHT_TAN:
  396.                         curPoint = object.upoint;
  397.                         curCmpnt = object.cmpnt;
  398.                         break;
  399.  
  400.                     default:
  401.                         curPoint = NULL;
  402.             }
  403.             break;
  404.         }
  405.     }
  406.     glutPostRedisplay();
  407. }
  408.  
  409. /*---------------------------------------------------------------------------*/
  410. /*    Motion
  411. /*---------------------------------------------------------------------------*/
  412. static void
  413. Motion( int x, int y )
  414. {
  415.     Mousex = x;
  416.     Mousey = H-y;
  417.     if (mouse.leftdown)
  418.     {
  419.         switch (curType)
  420.         {
  421.             case POINT:
  422.                 update = MovePoint( Mousex, Mousey );
  423.                 break;
  424.  
  425.             case LEFT_TAN:
  426.                 update = MoveTangente( -1, Mousex, Mousey );
  427.                 break;
  428.  
  429.             case RIGHT_TAN:
  430.                 update = MoveTangente( 1, Mousex, Mousey );
  431.                 break;
  432.         }
  433.     }
  434.     glutPostRedisplay();
  435. }
  436.  
  437. /*---------------------------------------------------------------------------*/
  438. /*            YACME_makeMenu
  439. /*---------------------------------------------------------------------------*/
  440.  
  441. #define    CONTINUOUS_ITEM    5
  442. #define    MANUAL_ITEM        4
  443. #define    APPLY_ITEM        3
  444. #define    RESET_ITEM        2
  445. #define    CLOSE_ITEM        1
  446.  
  447. #define    RED_ITEM    10
  448. #define    GREEN_ITEM    11
  449. #define    BLUE_ITEM    12
  450. #define    ALPHA_ITEM    13
  451.  
  452. #define    CONSTANT_ITEM    22
  453. #define    LINEAR_ITEM        21
  454. #define    POLYNOM_ITEM    20
  455.  
  456. #define    EDIT_RED_ITEM    30
  457. #define    EDIT_GREEN_ITEM    31
  458. #define    EDIT_BLUE_ITEM    32
  459. #define    EDIT_ALPHA_ITEM    33
  460.  
  461. void
  462. YACME_makeMenu(void)
  463. {
  464.     YACME_edit_menu = glutCreateMenu( YACME_menuFunc );
  465.     glutAddMenuEntry( "red", EDIT_RED_ITEM );
  466.     glutAddMenuEntry( "green", EDIT_GREEN_ITEM );
  467.     glutAddMenuEntry( "blue", EDIT_BLUE_ITEM );
  468.     glutAddMenuEntry( "alpha", EDIT_ALPHA_ITEM );
  469.  
  470.     YACME_mode_menu = glutCreateMenu( YACME_menuFunc );
  471.     glutAddMenuEntry( "Constant  ", CONSTANT_ITEM );
  472.     glutAddMenuEntry( "Linear    ", LINEAR_ITEM );
  473.     glutAddMenuEntry( "Polynomial", POLYNOM_ITEM );
  474.  
  475.     YACME_switch_menu = glutCreateMenu( YACME_menuFunc );
  476.     glutAddMenuEntry( "Red    on", RED_ITEM );
  477.     glutAddMenuEntry( "Green on", GREEN_ITEM );
  478.     glutAddMenuEntry( "Blue   on", BLUE_ITEM );
  479.     glutAddMenuEntry( "Alpha on", ALPHA_ITEM );
  480.  
  481.     YACME_menu = glutCreateMenu( YACME_menuFunc );
  482.     glutAddMenuEntry( "Manual    ", MANUAL_ITEM );
  483.     glutAddMenuEntry( "Apply", APPLY_ITEM );
  484.     glutAddMenuEntry( "Reset", RESET_ITEM );
  485.     glutAddMenuEntry( "Close", CLOSE_ITEM );
  486.     glutAddSubMenu(   "Mode... ", YACME_mode_menu );
  487.     glutAddSubMenu(   "Switch... ", YACME_switch_menu );
  488.     glutAddSubMenu(   "Edit... ", YACME_edit_menu );
  489.  
  490.     glutAttachMenu( GLUT_RIGHT_BUTTON );
  491. }
  492.  
  493. /*---------------------------------------------------------------------------*/
  494. /*    YACME_menuFunc
  495. /*---------------------------------------------------------------------------*/
  496. static void
  497. YACME_menuFunc( int item )
  498. {
  499.     switch( item )
  500.     {
  501.         case CLOSE_ITEM:
  502.             break;
  503.  
  504.         case RESET_ITEM:
  505.             if (applyCB) (*applyCB)();
  506.             else if (newmapCB) (*newmapCB)();
  507.             ResetCMap();
  508.             curPoint = NULL;
  509.             break;
  510.  
  511.         case APPLY_ITEM:
  512.             if (applyCB) (*applyCB)();
  513.             else if (newmapCB) (*newmapCB)();
  514.             ApplyCMap();
  515.             break;
  516.  
  517.         case MANUAL_ITEM:    /* switch to continuous */
  518.             glutChangeToMenuEntry( 1, "Continuous", CONTINUOUS_ITEM );
  519.             YACME_refresh = CONTINUOUS;
  520.             break;
  521.  
  522.         case CONTINUOUS_ITEM: /* switch to manual */
  523.             glutChangeToMenuEntry( 1, "Manual    ", MANUAL_ITEM );
  524.             if (newmapCB) (*newmapCB)();
  525.             ApplyCMap();
  526.             YACME_refresh = MANUAL;
  527.             break;
  528.  
  529.         case RED_ITEM:
  530.             DrawCurve[0] = !DrawCurve[0];
  531.             if (DrawCurve[0])
  532.                 glutChangeToMenuEntry( 1, "Red     on", RED_ITEM );
  533.             else
  534.                 glutChangeToMenuEntry( 1, "Red    off", RED_ITEM );
  535.             curPoint = NULL;
  536.             break;
  537.  
  538.         case GREEN_ITEM:
  539.             DrawCurve[1] = !DrawCurve[1];
  540.             if (DrawCurve[1])
  541.                 glutChangeToMenuEntry( 2, "Green on", GREEN_ITEM );
  542.             else
  543.                 glutChangeToMenuEntry( 2, "Green off", GREEN_ITEM );
  544.             curPoint = NULL;
  545.             break;
  546.  
  547.         case BLUE_ITEM:
  548.             DrawCurve[2] = !DrawCurve[2];
  549.             if (DrawCurve[2])
  550.                 glutChangeToMenuEntry( 3, "Blue   on", BLUE_ITEM );
  551.             else
  552.                 glutChangeToMenuEntry( 3, "Blue   off", BLUE_ITEM );
  553.             curPoint = NULL;
  554.             break;
  555.  
  556.         case ALPHA_ITEM:
  557.             DrawCurve[0] = !DrawCurve[3];
  558.             if (DrawCurve[3])
  559.                 glutChangeToMenuEntry( 4, "Alpha on", ALPHA_ITEM );
  560.             else
  561.                 glutChangeToMenuEntry( 4, "Alpha off", ALPHA_ITEM );
  562.             curPoint = NULL;
  563.             break;
  564.  
  565.         case CONSTANT_ITEM:
  566.             if (curPoint != NULL)
  567.             {
  568.                 update = 1;
  569.                 curPoint->mode = CONSTANT;
  570.             }
  571.             break;
  572.  
  573.         case LINEAR_ITEM:
  574.             if (curPoint != NULL)
  575.             {
  576.                 update = 1;
  577.                 curPoint->mode = LINEAR;
  578.             }
  579.             break;
  580.  
  581.         case POLYNOM_ITEM:
  582.             if (curPoint != NULL)
  583.             {
  584.                 update = 1;
  585.                 curPoint->mode = POLYNOMIAL;
  586.             }
  587.             break;
  588.  
  589.         case EDIT_RED_ITEM:
  590.         case EDIT_GREEN_ITEM:
  591.         case EDIT_BLUE_ITEM:
  592.         case EDIT_ALPHA_ITEM:
  593.             curCmpnt = item-30;
  594.             curPoint = userPoint[curCmpnt];
  595.             break;
  596.     }
  597.     glutPostRedisplay();
  598. }
  599.  
  600. /*---------------------------------------------------------------------------*/
  601. /*    output
  602. /*---------------------------------------------------------------------------*/
  603. static void
  604. output( float x, float y, char *string )
  605. {
  606.     int len, i;
  607.  
  608.     glRasterPos2f(x, y);
  609.     len = strlen(string);
  610.     for (i = 0; i < len; i++)
  611.     {
  612.         glutBitmapCharacter(GLUT_BITMAP_8_BY_13, string[i]);
  613.     }
  614. }
  615.  
  616. /*---------------------------------------------------------------------------*/
  617. /*    Redraw
  618. /*---------------------------------------------------------------------------*/
  619. static void
  620. Redraw( void )
  621. {
  622.     int    i, j, ndx, cmpnt, priority[4];
  623.     Tangente *tg;
  624.     UserPoint *upoint;
  625.     char string[256];
  626.  
  627.     if (update)
  628.     {
  629.         modifiedCurve[curCmpnt] = 1;
  630.         YACME_update( curCmpnt, curPoint );
  631.         if ( newmapCB && (YACME_refresh == CONTINUOUS))
  632.             (*newmapCB)();
  633.         update = 0;
  634.     }
  635.  
  636.     glClear( GL_COLOR_BUFFER_BIT );
  637.  
  638. /*
  639.     Barettes representant la table des couleurs
  640.     -------------------------------------------
  641. */
  642.     glBegin( GL_TRIANGLE_STRIP );
  643.         glColor3f(TabCmpnt(0,0), TabCmpnt(1,0), TabCmpnt(2,0));
  644.         glVertex2f( 0., 270.*LUTRATIO );
  645.         glVertex2f( 0., 310.*LUTRATIO );
  646.         glVertex2f( .5, 270.*LUTRATIO );
  647.         glVertex2f( .5, 310.*LUTRATIO );
  648.     glEnd();
  649.     for ( i=1; i<MAXNDX; i++ )
  650.     {
  651.         float x=(float)i - .5;
  652.         glBegin( GL_TRIANGLE_STRIP );
  653.             glColor3f(TabCmpnt(0,i), TabCmpnt(1,i), TabCmpnt(2,i));
  654.             glVertex2f( x, 270.*LUTRATIO );
  655.               glVertex2f( x, 310.*LUTRATIO );
  656.             glVertex2f( x+1., 270.*LUTRATIO );
  657.             glVertex2f( x+1., 310.*LUTRATIO );
  658.         glEnd();
  659.      }
  660.     glBegin( GL_TRIANGLE_STRIP );
  661.         glColor3f(TabCmpnt(0,MAXNDX), TabCmpnt(1,MAXNDX), TabCmpnt(2,MAXNDX));
  662.         glVertex2f( (float)MAXNDX-.5, 270.*LUTRATIO );
  663.         glVertex2f( (float)MAXNDX-.5, 310.*LUTRATIO );
  664.         glVertex2f( (float)MAXNDX, 270.*LUTRATIO );
  665.         glVertex2f( (float)MAXNDX, 310.*LUTRATIO );
  666.     glEnd();
  667.  
  668. /*
  669.     Graphe y = cpste(x)
  670.     -------------------
  671. */ 
  672.     glColor3f(0.,0.,0.);
  673.     glBegin( GL_TRIANGLE_STRIP );
  674.         glVertex2f( 0., 0. );
  675.         glVertex2f( (float) MAXNDX, 0. );
  676.         glVertex2f( 0., (float) MAXNDX );
  677.         glVertex2f( (float) MAXNDX, (float) MAXNDX );
  678.     glEnd();
  679.  
  680. /*
  681.     Curves y = cpste(x)
  682.     --------------------
  683. */
  684.     for ( i=0; i<curCmpnt; i++)
  685.     {
  686.         priority[i] = i;
  687.     }
  688.     for ( i=curCmpnt+1; i<4; i++ ) {
  689.         priority[i-1] = i;
  690.     }
  691.     priority[3] = curCmpnt;
  692.  
  693.     cmpnt = priority[0];
  694.     for ( i=0; i<4; i++, cmpnt=priority[i] ) if ( DrawCurve[cmpnt] )
  695.     {
  696.  
  697.         switch (cmpnt)
  698.         {
  699.             case 3: glColor3f(1.,1.,1.); break;
  700.             case 2: glColor3f(0.,0.,1.); break;
  701.             case 1: glColor3f(0.,1.,0.); break;
  702.             case 0: glColor3f(1.,0.,0.); break;
  703.         }
  704.  
  705.         for ( j=0; j<MAXNDX; j++ )
  706.         {
  707.             glBegin( GL_LINES );
  708.                 glVertex2f( (float)j, (float)MAXNDX*TabCmpnt(cmpnt,j) );
  709.                 glVertex2f( (float)(j+1), (float)MAXNDX*TabCmpnt(cmpnt,j+1) );
  710.             glEnd();
  711.         }
  712.     }
  713.  
  714.     if ( curPoint != NULL )
  715.     {
  716.         float h;
  717. /*
  718.         user defined points
  719.         -------------------
  720. */
  721.         upoint = userPoint[curCmpnt];
  722.         do {
  723. /*
  724.             Point
  725.             -----
  726. */
  727. #define    DIMPOINT (2.*LUTRATIO)
  728.  
  729.             glBegin( GL_TRIANGLE_STRIP );
  730.                 glVertex2f( upoint->x-DIMPOINT, upoint->y-DIMPOINT );
  731.                 glVertex2f( upoint->x-DIMPOINT, upoint->y+DIMPOINT );
  732.                 glVertex2f( upoint->x+DIMPOINT, upoint->y-DIMPOINT );
  733.                 glVertex2f( upoint->x+DIMPOINT, upoint->y+DIMPOINT );
  734.             glEnd();
  735. /*
  736.             Tangente
  737.             --------
  738. */
  739.             tg = &upoint->tg;
  740.             if (upoint->last ? upoint->last->mode == POLYNOMIAL : 0)
  741.             {
  742.                 glBegin( GL_LINES );
  743.                     glVertex2f( tg->x0, tg->y0 );
  744.                     glVertex2f( upoint->x, upoint->y );
  745.                 glEnd();
  746.                 glBegin( GL_LINE_LOOP );
  747.                     glVertex2f( tg->x0-DIMPOINT, tg->y0-DIMPOINT );
  748.                     glVertex2f( tg->x0-DIMPOINT, tg->y0+DIMPOINT );
  749.                     glVertex2f( tg->x0+DIMPOINT, tg->y0+DIMPOINT );
  750.                     glVertex2f( tg->x0+DIMPOINT, tg->y0-DIMPOINT );
  751.                 glEnd();
  752.             }
  753.             if (upoint->mode == POLYNOMIAL)
  754.             {
  755.                 glBegin( GL_LINES );
  756.                     glVertex2f( upoint->x, upoint->y );
  757.                     glVertex2f( tg->x1, tg->y1 );
  758.                 glEnd();
  759.                 glBegin( GL_LINE_LOOP );
  760.                     glVertex2f( tg->x1-DIMPOINT, tg->y1-DIMPOINT );
  761.                     glVertex2f( tg->x1-DIMPOINT, tg->y1+DIMPOINT );
  762.                     glVertex2f( tg->x1+DIMPOINT, tg->y1+DIMPOINT );
  763.                     glVertex2f( tg->x1+DIMPOINT, tg->y1-DIMPOINT );
  764.                 glEnd();
  765.             }
  766.             
  767.         } while ( (upoint=upoint->next) != NULL );
  768.  
  769. /*
  770.         Highlight current point
  771.         -----------------------
  772. */
  773.         ndx = curPoint->x;
  774.         h = curPoint->y;
  775.         switch (curCmpnt)
  776.         {
  777.             case 3: glColor3f(1.,1.,1.); break;
  778.             case 2: glColor3f(0.,0.,1.); break;
  779.             case 1: glColor3f(0.,1.,0.); break;
  780.             case 0: glColor3f(1.,0.,0.); break;
  781.         }
  782.         glBegin( GL_LINE_LOOP );
  783.             glVertex2f( (float)ndx-2.*DIMPOINT, h-2.*DIMPOINT );
  784.             glVertex2f( (float)ndx-2.*DIMPOINT, h+2.*DIMPOINT );
  785.             glVertex2f( (float)ndx+2.*DIMPOINT, h+2.*DIMPOINT );
  786.             glVertex2f( (float)ndx+2.*DIMPOINT, h-2.*DIMPOINT );
  787.         glEnd();
  788.     }
  789.     else
  790.     {
  791.         float x, y;
  792.         OrthoTransform( Mousex, Mousey, &x, &y );
  793.         ndx = (int) SUP( INF(x,(float)MAXNDX), 0 );
  794.     }
  795.  
  796. /*
  797.     Coordinates text string
  798.     -----------------------
  799. */
  800.     glColor3f( 0., 0., 0. );
  801.     sprintf( string,
  802.         "%.5d: rgba %.3f %.3f %.3f %.3f",
  803.         ndx,
  804.         TabCmpnt(0,ndx),
  805.         TabCmpnt(1,ndx),
  806.         TabCmpnt(2,ndx),
  807.         TabCmpnt(3,ndx)
  808.     );
  809.     output( LUTRATIO, 257.*LUTRATIO, string );
  810.  
  811.     glutSwapBuffers();
  812. }
  813.  
  814. /*---------------------------------------------------------------------------*/
  815. /*            YACME_pick
  816. /*---------------------------------------------------------------------------*/
  817. void
  818. YACME_pick( int mousex, int mousey, PickObject *obj )
  819. {
  820.  int    cmpnt, i, priority[4];
  821.  float    x, y, val;
  822.  Tangente *tg;
  823.  UserPoint *upoint;
  824.  float pickrad;
  825.  
  826.  obj->type = -1;
  827.  OrthoTransform( mousex, mousey, &x, &y );
  828.  
  829. /*
  830.  On travaille en priorite sur les objets definis par l'utilisateur
  831.  -----------------------------------------------------------------
  832. */
  833.  for ( i=0; i<curCmpnt; i++) {
  834.     priority[i] = i;
  835.  }
  836.  for ( i=curCmpnt+1; i<4; i++ ) {
  837.     priority[i-1] = i;
  838.  }
  839.  priority[3] = curCmpnt;
  840.  
  841.  pickrad = 3.*LUTRATIO;
  842.  cmpnt = priority[3];
  843.  for ( i=3; i>=0; i--, cmpnt=priority[i] ) if ( DrawCurve[cmpnt] ) {
  844.  
  845.     upoint = userPoint[cmpnt];
  846.     while ( upoint != NULL ) {
  847. /*
  848.         On cherche le POINT
  849. */
  850.         if ( ABS(y-upoint->y) < pickrad && ABS(x-upoint->x) < pickrad ) {
  851.             obj->upoint    = upoint;
  852.             obj->cmpnt    = cmpnt;
  853.             obj->type    = POINT;
  854.             return;
  855.         }
  856. /*
  857.         On cherche la demi-tangente GAUCHE
  858. */
  859.         tg = &upoint->tg;
  860.         if ( ABS(x-tg->x0) < pickrad && ABS(y-tg->y0) < pickrad ) {
  861.             obj->upoint    = upoint;
  862.             obj->cmpnt    = cmpnt;
  863.             obj->type    = LEFT_TAN;
  864.             return;
  865.         }
  866. /*
  867.         On cherche la demi-tangente DROITE
  868. */
  869.         if ( ABS(x-tg->x1) < pickrad && ABS(y-tg->y1) < pickrad ) {
  870.             obj->upoint    = upoint;
  871.             obj->cmpnt    = cmpnt;
  872.             obj->type    = RIGHT_TAN;
  873.             return;
  874.         }
  875.         upoint = upoint->next;
  876.     }
  877. /*
  878.     Puis on cherche les coordonnees sur la CURVE
  879.     (On considere la precision suffisante pour le picking suivant l'axe X)
  880.     Remarque : on ne sort pas en ce cas, car la priorite est sur les objets
  881.     utilisateurs.
  882. */
  883.     upoint = userPoint[cmpnt];
  884.     while ( upoint->next->x < x ) {
  885.         upoint = upoint->next;
  886.         if ( upoint->next == NULL ) return;
  887.     }
  888.  
  889.     val = INF( SUP( Polynome4(x,upoint->polynome), 0.), (float)MAXNDX );
  890.     if ( ABS(y-val) < pickrad ) {
  891.         obj->cmpnt    = cmpnt;
  892.         obj->ndx    = ((x-(int)x)<.5) ? (int)x : (int)x+1;
  893.         obj->type    = CURVE;
  894.         return;
  895.     }
  896.  
  897.  }
  898. }
  899.  
  900. /*---------------------------------------------------------------------------*/
  901. /*            YACME_update
  902. /*---------------------------------------------------------------------------*/
  903. void
  904. YACME_update( int cmpnt, UserPoint *upoint )
  905. {
  906.  int    i;
  907.  float    val, t0, t1;
  908.  Tangente *tg;
  909.  
  910.  tg = &upoint->tg;
  911.  if ( tg->x1 != tg->x0 ) {
  912.     t0 = (tg->y1-tg->y0) / (tg->x1-tg->x0);
  913.  } else {
  914.     t0 = (tg->y1-tg->y0)*10000.;
  915.  }
  916.  
  917.  TabCmpnt(cmpnt,(int) upoint->x) = upoint->y/(float)MAXNDX;
  918.  if ( upoint->last != NULL ) {
  919.  
  920.     tg = &upoint->last->tg;
  921.     if ( tg->x1 != tg->x0 ) {
  922.         t1 = (tg->y1-tg->y0) / (tg->x1-tg->x0);
  923.     } else {
  924.         t1 = (tg->y1-tg->y0)*10000.;
  925.     }
  926.  
  927.     GetPolynome(
  928.         upoint->last->mode,
  929.         upoint->last->x,
  930.         upoint->last->y,
  931.         t1,
  932.         upoint->x,
  933.         upoint->y,
  934.         t0,
  935.         upoint->last->polynome
  936.     );
  937.  
  938.     for ( i=1+(int) upoint->last->x; i<(int) upoint->x; i++ ) {
  939.         val = Polynome4((float) i, upoint->last->polynome)/(float)MAXNDX;
  940.         TabCmpnt(cmpnt,i) = INF( SUP(val,0.), 1. );
  941.     }
  942.  }
  943.  
  944.  if ( upoint->next != NULL ) {
  945.  
  946.     tg = &upoint->next->tg;
  947.     if ( tg->x1 != tg->x0 ) {
  948.         t1 = (tg->y1-tg->y0) / (tg->x1-tg->x0);
  949.     } else {
  950.         t1 = (tg->y1-tg->y0)*10000.;
  951.     }
  952.  
  953.     GetPolynome(
  954.         upoint->mode,
  955.         upoint->x,
  956.         upoint->y,
  957.         t0,
  958.         upoint->next->x,
  959.         upoint->next->y,
  960.         t1,
  961.         upoint->polynome
  962.     );
  963.  
  964.     for ( i=1+(int) upoint->x; i<(int) upoint->next->x; i++ ) {
  965.         val = Polynome4( (float) i, upoint->polynome )/(float)MAXNDX;
  966.         TabCmpnt(cmpnt,i) = INF( SUP(val,0.), 1. );
  967.     }
  968.     TabCmpnt(cmpnt,(int) upoint->next->x) = upoint->next->y/(float)MAXNDX;
  969.  }
  970. }
  971.  
  972. /*---------------------------------------------------------------------------*/
  973. /*            freePointList
  974. /*---------------------------------------------------------------------------*/
  975. static void
  976. freePointList( UserPoint *upoint )
  977. {
  978.     while (upoint != NULL)
  979.     {
  980.         UserPoint *unext = upoint->next;
  981.         freePoint( upoint );
  982.         upoint = unext;
  983.     }
  984. }
  985.  
  986. /*---------------------------------------------------------------------------*/
  987. /*            clonePointList
  988. /*---------------------------------------------------------------------------*/
  989. static UserPoint *
  990. clonePointList( UserPoint *base )
  991. {
  992.     UserPoint *clone, *upoint;
  993.  
  994.     if (base == NULL) return NULL;
  995.  
  996.     newPoint( clone );
  997.     upoint = clone;
  998.  
  999.     memcpy( upoint, base, sizeof(UserPoint) );
  1000.     upoint->last = NULL;
  1001.     upoint->next = NULL;
  1002.  
  1003.     while (base->next != NULL)
  1004.     {
  1005.         base = base->next;
  1006.         newPoint( upoint->next );
  1007.         memcpy( upoint->next, base, sizeof(UserPoint) );
  1008.         upoint->next->last = upoint;
  1009.         upoint->next->next = NULL;
  1010.         upoint = upoint->next;
  1011.     }
  1012.  
  1013.     return clone;
  1014. }
  1015.  
  1016. /*---------------------------------------------------------------------------*/
  1017. /*            ApplyCMap
  1018. /*---------------------------------------------------------------------------*/
  1019. void
  1020. ApplyCMap(void)
  1021. {
  1022.     int    i;
  1023.  
  1024.     for (i=0; i<4; i++) if ( modifiedCurve[i] )
  1025.     {
  1026.         freePointList( userPointSvg[i] );
  1027.         userPointSvg[i] = clonePointList( userPoint[i] );
  1028.         modifiedCurve[i] = 0;
  1029.     }
  1030. }
  1031.  
  1032. /*---------------------------------------------------------------------------*/
  1033. /*            ResetCMap
  1034. /*---------------------------------------------------------------------------*/
  1035. void
  1036. ResetCMap(void)
  1037. {
  1038.     int    i;
  1039.     UserPoint *upoint;
  1040.  
  1041.     for (i=0; i<4; i++) if ( modifiedCurve[i] )
  1042.     {
  1043.         freePointList( userPoint[i] );
  1044.         userPoint[i] = clonePointList( userPointSvg[i] );
  1045.         modifiedCurve[i] = 0;
  1046.  
  1047.         for (upoint=userPoint[i]; upoint!=NULL; upoint=upoint->next )
  1048.             YACME_update( i, upoint );
  1049.     }
  1050. }
  1051.  
  1052. /*---------------------------------------------------------------------------*/
  1053. /*            InsertPoint
  1054. /*---------------------------------------------------------------------------*/
  1055. int
  1056. InsertPoint( PickObject *obj )
  1057. {
  1058.  float    dx, dy, slope, coeff[4];
  1059.  int    i;
  1060.  Tangente *tg;
  1061.  UserPoint *upoint, *userpoint;
  1062.  
  1063.  upoint = userPoint[obj->cmpnt];
  1064.  while ( (int) upoint->next->x <= obj->ndx ) {
  1065.     upoint = upoint->next;
  1066.     if ( upoint->next == NULL ) return 0;
  1067.  }
  1068.  if ( (int) upoint->x == obj->ndx ) {
  1069.     obj->upoint = upoint;
  1070.     return POINT;
  1071.  }
  1072.  
  1073.  newPoint( userpoint );
  1074.  
  1075.  userpoint->x = (float) obj->ndx;
  1076.  userpoint->y = Polynome4( obj->ndx, upoint->polynome );
  1077.  userpoint->y = SUP( INF(userpoint->y, (float)MAXNDX), 0. );
  1078.  userpoint->mode = upoint->mode;
  1079.  for ( i=0; i<4; i++ ) {
  1080.     userpoint->polynome[i] = upoint->polynome[i];
  1081.  }
  1082.  userpoint->next = upoint->next;
  1083.  userpoint->last = upoint;
  1084.  upoint->next = userpoint;
  1085.  userpoint->next->last = userpoint;
  1086.  
  1087. /*
  1088.  calcul de slope = P'(index)
  1089.  ---------------------------
  1090. */
  1091.  
  1092.  if ( userpoint->y == (float)MAXNDX || userpoint->y == 0. ) {
  1093.     dx = 25.;
  1094.     dy = 0.;
  1095.  } else {
  1096.     coeff[0] = userpoint->polynome[0]*3.;
  1097.     coeff[1] = userpoint->polynome[1]*2.;
  1098.     coeff[2] = userpoint->polynome[2];
  1099.     slope = coeff[0];
  1100.     for (i=1; i<3; i++) {
  1101.         slope *= (float) obj->ndx;    
  1102.         slope += coeff[i];
  1103.     }
  1104. /*
  1105.     Rappel :
  1106.     cos( arctg(x) ) = 1/sqr( 1 + x^2 );
  1107.     sin( arctg(x) ) = |x|/sqr( 1 + x^2 );
  1108. */
  1109.     dx = 25. / fsqrt( slope*slope + 1. );
  1110.     dy = dx*slope;
  1111.  }
  1112.  dx *= LUTRATIO;
  1113.  dy *= LUTRATIO;
  1114.  
  1115.  tg = &userpoint->tg;
  1116.  tg->x0 = userpoint->x - dx;
  1117.  tg->x1 = userpoint->x + dx;
  1118.  tg->y0 = userpoint->y - dy;
  1119.  tg->y1 = userpoint->y + dy;
  1120.  
  1121.  obj->upoint = userpoint;
  1122.  return POINT;
  1123. }
  1124.  
  1125. /*---------------------------------------------------------------------------*/
  1126. /*            DeletePoint
  1127. /*---------------------------------------------------------------------------*/
  1128. void
  1129. DeletePoint( int cmpnt, UserPoint *upoint )
  1130. {
  1131.     if ( upoint == NULL || upoint->last == NULL || upoint->next == NULL )
  1132.         return;
  1133.     upoint->last->next = upoint->next;
  1134.     upoint->next->last = upoint->last;
  1135.     YACME_update( cmpnt, upoint->last );
  1136.     freePoint( upoint );
  1137. }
  1138.  
  1139. /*---------------------------------------------------------------------------*/
  1140. /*            MovePoint
  1141. /*---------------------------------------------------------------------------*/
  1142. int
  1143. MovePoint( int mousex, int mousey )
  1144. {
  1145.     float    x, y, dx, dy, minx, maxx;
  1146.  
  1147.     OrthoTransform( mousex, mousey, &x, &y );
  1148.  
  1149.     y = SUP( INF(y,(float)MAXNDX), 0. );
  1150.     x = ((x-(int)x)<.5) ? (float)(int)x : (float)(int)(x+1);
  1151.     y = ((y-(int)y)<.5) ? (float)(int)y : (float)(int)(y+1);
  1152.     if ( curPoint->next != NULL && curPoint->last!= NULL )
  1153.     {
  1154.         minx = curPoint->last->x + 1.;
  1155.         maxx = curPoint->next->x - 1.;
  1156.         x = SUP( INF(x, maxx), minx );
  1157.  
  1158.         dx = (float)x - curPoint->x;
  1159.         curPoint->x = (float) x;
  1160.         curPoint->tg.x0 += (float) dx;
  1161.         curPoint->tg.x1 += (float) dx;
  1162.     }
  1163.     dy = (float)y - curPoint->y;
  1164.     curPoint->y = (float)y;
  1165.     curPoint->tg.y0 += (float) dy;
  1166.     curPoint->tg.y1 += (float) dy;
  1167.  
  1168.     return 1;
  1169. }
  1170.  
  1171. /*---------------------------------------------------------------------------*/
  1172. /*            MoveTangente
  1173. /*---------------------------------------------------------------------------*/
  1174. int
  1175. MoveTangente( int sens, int mousex, int mousey )
  1176. {
  1177.     float    x, y, dx, dy, slope;
  1178.     Tangente *tg;
  1179.  
  1180.     OrthoTransform( mousex, mousey, &x, &y );
  1181.  
  1182.     if ( sens == -1 )
  1183.     {
  1184.         x = INF(x, curPoint->x);
  1185.     }
  1186.     else
  1187.     {
  1188.         x = SUP(x, curPoint->x);
  1189.     }
  1190.     if ( x != curPoint->x )
  1191.     {
  1192.         slope =        (curPoint->y - y);
  1193.         slope /=    (curPoint->x - x);
  1194.         dx = 25. / fsqrt( slope*slope + 1. );
  1195.         dy = dx*slope;
  1196.     }
  1197.     else
  1198.     {
  1199.         dx = 0.;
  1200.         dy = (curPoint->y < y) ? sens*25. : -sens*25.;
  1201.     }
  1202.  
  1203.     dx *= LUTRATIO;
  1204.     dy *= LUTRATIO;
  1205.  
  1206.     tg = &curPoint->tg;
  1207.     tg->x0 = curPoint->x;
  1208.     tg->y0 = curPoint->y;
  1209.     if ( curPoint->last != NULL ) {
  1210.         tg->x0 -= dx;
  1211.         tg->y0 -= dy;
  1212.     }
  1213.     tg->x1 = curPoint->x;
  1214.     tg->y1 = curPoint->y;
  1215.     if ( curPoint->next != NULL )
  1216.     {
  1217.         tg->x1 += dx;
  1218.         tg->y1 += dy;
  1219.     }
  1220.  
  1221.     return 1;
  1222. }
  1223.  
  1224. /*---------------------------------------------------------------------------*/
  1225. /*            GetPolynome
  1226. /*---------------------------------------------------------------------------*/
  1227. /*
  1228.     we want a polynom P(x) = Ax^3 + Bx^2 + Cx + D
  1229.     so that : P(a0) = b0, P'(a0) = t0, P(a1) = b1, P'(a1) = t1 
  1230.     i.e.
  1231.  
  1232.     | a0^3        a0^2    a0    1 | |A|      |b0|
  1233.     | a1^3        a1^2    a1    1 | |B| = |b1|
  1234.     | 3a0^2        2a0        1    0 | |C|      |t0|
  1235.     | 3a1^2        2a1        1    0 | |D|   |t1|
  1236. */
  1237. void
  1238. GetPolynome(
  1239.     int mode,
  1240.     float a0, float b0, float t0,
  1241.     float a1, float b1, float t1,
  1242.     float coeff[4] )
  1243. {
  1244.     Matrix    mat, INV_mat;
  1245.     int    i;
  1246.     float    val;
  1247.  
  1248.     switch (mode)
  1249.     {
  1250.         case CONSTANT:
  1251. /*            we want P(x) = b0 */
  1252.             coeff[0] = 0.;
  1253.             coeff[1] = 0.;
  1254.             coeff[2] = 0.;
  1255.             coeff[3] = b0;
  1256.             break;
  1257.  
  1258.         case LINEAR:
  1259. /*
  1260.             we want P(x) = b0 + (x-a0)/(a1-a0)*(b1-b0)
  1261.             i.e. P(x) = x*[(b1-b0)/(a1-a0)] + b0 - a0*[(b1-b0)/(a1-a0)]
  1262. */
  1263.             val = (b1-b0)/(a1-a0);
  1264.             coeff[0] = 0.;
  1265.             coeff[1] = 0.;
  1266.             coeff[2] = val;
  1267.             coeff[3] = b0 - a0*val;
  1268.             break;
  1269.  
  1270.         case POLYNOMIAL:
  1271. /*
  1272.             we want a polynom P(x) = Ax^3 + Bx^2 + Cx + D
  1273.             so that : P(a0) = b0, P'(a0) = t0, P(a1) = b1, P'(a1) = t1 
  1274.             i.e.
  1275.         
  1276.             | a0^3        a0^2    a0    1 | |A|      |b0|
  1277.             | a1^3        a1^2    a1    1 | |B| = |b1|
  1278.             | 3a0^2        2a0        1    0 | |C|      |t0|
  1279.             | 3a1^2        2a1        1    0 | |D|   |t1|
  1280. */
  1281.             val = 1.;
  1282.             for (i=3; i>=0; i--)
  1283.             {
  1284.                 mat[0][i] = val;
  1285.                 val *= a0;
  1286.             }
  1287.         
  1288.             val = 1.;
  1289.             for (i=3; i>=0; i--)
  1290.             {
  1291.                 mat[1][i] = val;
  1292.                 val *= a1;
  1293.             }
  1294.         
  1295.             mat[2][3] = 0.;
  1296.             mat[2][2] = 1.;
  1297.             mat[2][1] = 2.*a0;
  1298.             mat[2][0] = 3.*a0*a0;
  1299.         
  1300.             mat[3][3] = 0.;
  1301.             mat[3][2] = 1.;
  1302.             mat[3][1] = 2.*a1;
  1303.             mat[3][0] = 3.*a1*a1;
  1304.         
  1305.             invertmat( mat, INV_mat );
  1306.         
  1307.             for (i=0; i<4; i++)
  1308.                 coeff[i] = INV_mat[i][0]*b0 +
  1309.                     INV_mat[i][1]*b1 +
  1310.                     INV_mat[i][2]*t0 +
  1311.                     INV_mat[i][3]*t1;
  1312.             break;
  1313.     }
  1314. }
  1315.  
  1316. /*---------------------------------------------------------------------------*/
  1317. /*            OrthoTransform
  1318. /*---------------------------------------------------------------------------*/
  1319. void
  1320. OrthoTransform( int mx, int my, float *x, float *y )
  1321. {
  1322.  float    xf, yf;
  1323.  
  1324.  xf =    (float) mx;
  1325.  xf /=    (float) W;
  1326.  xf *=    (float) (RIGHT - LEFT);
  1327.  xf +=    (float) LEFT;
  1328.  
  1329.  yf =    (float) my;
  1330.  yf /=    (float) H;
  1331.  yf *=    (float) (TOP - BOTTOM);
  1332.  yf +=    (float) BOTTOM;
  1333.  
  1334.  *x = xf;
  1335.  *y = yf;
  1336. }
  1337.  
  1338. /*---------------------------------------------------------------------------*/
  1339. /*            Polynome4
  1340. /*---------------------------------------------------------------------------*/
  1341. float
  1342. Polynome4( float x, float *coeff )
  1343. {
  1344.  int    j;
  1345.  float    val = coeff[0];
  1346.  
  1347.  for (j=1; j<4; j++) {
  1348.     val *= x;
  1349.     val += coeff[j];
  1350.  }
  1351.  
  1352.  return    val;
  1353. }
  1354.  
  1355. /*---------------------------------------------------------------------------*/
  1356. /*            MAIN
  1357. /*---------------------------------------------------------------------------*/
  1358. #ifdef    YACME_DBG
  1359. #include "RGBA.h"
  1360. int
  1361. main( int argc, char *argv[] )
  1362. {
  1363.     glutInit( &argc, argv );
  1364.  
  1365.     YACME_init(
  1366.         0, 0, WINWIDTH, WINHEIGHT,
  1367.         256, (float**)RGBA,
  1368.         NULL, NULL
  1369.     );
  1370.     glutMainLoop();
  1371.     return 0;             /* ANSI C requires main to return int. */
  1372. }
  1373. #endif
  1374.  
  1375.